﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using BrasilFramework.Controle.WPF.Comum;
using BrasilFramework.Controle.WPF.Comum.Validacao;

namespace BrasilFramework.Controle.WPF
{
    public class TextBox : System.Windows.Controls.TextBox
    {
        private readonly ValidatorManager _gerenciadorValidacao = new ValidatorManager();
        private readonly RequiredValidator _validadorObrigatoriedade = new RequiredValidator();
        private readonly RangeValidator _validadorValor = new RangeValidator();
        private readonly RegexValidator _validadorExpressao = new RegexValidator();

        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);
            _validadorObrigatoriedade.SetManagerAndControl(_gerenciadorValidacao, this);
            _validadorValor.SetManagerAndControl(_gerenciadorValidacao, this);
            _validadorExpressao.SetManagerAndControl(_gerenciadorValidacao, this);
            //Padding = new Thickness(Padding.Left, Padding.Top, Padding.Right + 24, Padding.Bottom);
            RegistrarValidacao();
        }

        private void RegistrarValidacao()
        {
            if (!IsInitialized) return;

            Text = string.Empty;

            //Marcar o texto ao entrar em foco
            GotFocus -= TextBox_GotFocus;
            if (DestacarFoco) GotFocus += TextBox_GotFocus;

            _validadorObrigatoriedade.Finalizar();

            //Configura obrigatoriedade
            if (Obrigatorio)
            {
                _validadorObrigatoriedade.ErrorMessage = string.Format(Mensagem.CampoObrigatorio, NomeAmigavel);
                _validadorObrigatoriedade.Inicializar();
            }

            //Configura formato valor
            _validadorValor.Finalizar();

            _validadorValor.Filter = Filtro;

            string expressao = string.Empty;
            switch (Filtro)
            {
                case TextBoxFilterService.TipoFiltro.Data:
                    MaxLength = 10;
                    expressao = ExpressaoRegular.DATA;
                    break;
                case TextBoxFilterService.TipoFiltro.Hora:
                    MaxLength = 5;
                    expressao = ExpressaoRegular.HORA;
                    break;
                case TextBoxFilterService.TipoFiltro.Email:
                    expressao = ExpressaoRegular.ENDERECO_ELETRONICO;
                    break;
                case TextBoxFilterService.TipoFiltro.Nenhum:
                    break;
                default:
                    _validadorValor.ErrorMessage = string.Format(Mensagem.CampoInvalido, NomeAmigavel);
                    _validadorValor.Inicializar();
                    break;
            }

            if (!string.IsNullOrEmpty(Expressao)) expressao = Expressao;

            //Configura Expressão Regular
            _validadorExpressao.Finalizar();

            if (string.IsNullOrEmpty(expressao)) return;

            _validadorExpressao.Expression = expressao;
            _validadorExpressao.ErrorMessage = string.Format(Mensagem.CampoInvalido, NomeAmigavel);
            _validadorExpressao.Inicializar();
        }

        protected void TextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            if (!DestacarFoco || string.IsNullOrEmpty(Text)) return;

            SelectionStart = 0;
            SelectionLength = Text.Length;
        }

        public List<string> Erros()
        {
            List<ValidatorBase> validacao = _gerenciadorValidacao.ValidateAll();
            return validacao.Select(item => item.ErrorMessage).ToList();
        }

        #region Propriedades

        public static readonly DependencyProperty PropriedadeDestacarFoco =
            DependencyProperty.Register(
                "DestacarFoco",
                typeof(bool),
                typeof(TextBox),
                new PropertyMetadata(true, PropriedadeMudou));

        public static readonly DependencyProperty PropriedadeFitro =
            DependencyProperty.Register(
                "Filtro",
                typeof(TextBoxFilterService.TipoFiltro),
                typeof(TextBox),
                new PropertyMetadata(TextBoxFilterService.TipoFiltro.Nenhum, PropriedadeMudou));

        public static readonly DependencyProperty PropriedadeObrigatorio =
            DependencyProperty.Register(
                "Obrigatorio",
                typeof(bool),
                typeof(TextBox),
                new PropertyMetadata(false, PropriedadeMudou));

        public static readonly DependencyProperty PropriedadeNomeAmigavel =
            DependencyProperty.Register(
                "NomeAmigavel",
                typeof(string),
                typeof(TextBox),
                new PropertyMetadata(string.Empty, PropriedadeMudou));

        public static readonly DependencyProperty PropriedadeExpressao =
            DependencyProperty.Register(
                "Expressao",
                typeof(string),
                typeof(TextBox),
                new PropertyMetadata(string.Empty, PropriedadeMudou));

        [Description("Seleciona o conteúdo ao entrar em foco."), Category("Validação")]
        public bool DestacarFoco
        {
            get { return (bool)GetValue(PropriedadeDestacarFoco); }
            set { SetValue(PropriedadeDestacarFoco, value); }
        }

        [Description("Filtro que define como o campo deverá se comportar."), Category("Validação")]
        public TextBoxFilterService.TipoFiltro Filtro
        {
            get { return (TextBoxFilterService.TipoFiltro)GetValue(PropriedadeFitro); }
            set { SetValue(PropriedadeFitro, value); }
        }

        [Description("Obriga o preenchimento do campo."), Category("Validação")]
        public bool Obrigatorio
        {
            get { return (bool)GetValue(PropriedadeObrigatorio); }
            set { SetValue(PropriedadeObrigatorio, value); }
        }

        [Description("Nome amigável para o controle. Este nome será exibido nas mensagens de validação."),
         Category("Validação")]
        public string NomeAmigavel
        {
            get { return (string)GetValue(PropriedadeNomeAmigavel); }
            set { SetValue(PropriedadeNomeAmigavel, value); }
        }

        [Description("Expressão regular."), Category("Validação")]
        public string Expressao
        {
            get { return (string)GetValue(PropriedadeExpressao); }
            set { SetValue(PropriedadeExpressao, value); }
        }

        private static void PropriedadeMudou(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((TextBox)sender).RegistrarValidacao();
        }

        #endregion
    }
}